package com.openmanus.config.persistence;

import com.openmanus.config.OpenManusProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * 持久化自动配置类
 * 根据配置自动选择数据库和ORM框架
 * 
 * @author OpenManus Team
 * @version 1.0.0
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(OpenManusProperties.class)
public class PersistenceAutoConfiguration {

    private final OpenManusProperties properties;

    /**
     * 动态数据源配置
     */
    @Bean
    @Primary
    public DataSource dataSource() {
        OpenManusProperties.PersistenceProperties persistence = properties.getPersistence();
        OpenManusProperties.PersistenceProperties.DatabaseType dbType = persistence.getDatabase();
        OpenManusProperties.PersistenceProperties.PoolProperties pool = persistence.getPool();

        log.info("配置数据源: 数据库类型={}, ORM框架={}", 
                dbType.getName(), persistence.getOrm().getName());

        HikariConfig config = new HikariConfig();
        
        // 根据数据库类型设置驱动和URL
        config.setDriverClassName(dbType.getDriverClass());
        config.setJdbcUrl(buildJdbcUrl(dbType));
        config.setUsername(getDatabaseUsername(dbType));
        config.setPassword(getDatabasePassword(dbType));
        
        // 连接池配置
        config.setMaximumPoolSize(pool.getMaximumPoolSize());
        config.setMinimumIdle(pool.getMinimumIdle());
        config.setConnectionTimeout(pool.getConnectionTimeout());
        config.setIdleTimeout(pool.getIdleTimeout());
        config.setMaxLifetime(pool.getMaxLifetime());
        
        // 连接池优化配置
        config.setLeakDetectionThreshold(60000);
        config.setValidationTimeout(5000);
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        
        return new HikariDataSource(config);
    }

    /**
     * 构建JDBC URL
     */
    private String buildJdbcUrl(OpenManusProperties.PersistenceProperties.DatabaseType dbType) {
        return switch (dbType) {
            case POSTGRESQL -> String.format("jdbc:postgresql://%s:%s/%s",
                    System.getProperty("DB_HOST", "localhost"),
                    System.getProperty("DB_PORT", "5432"),
                    System.getProperty("DB_NAME", "openmanus"));
            case MYSQL -> String.format("jdbc:mysql://%s:%s/%s?useSSL=false&serverTimezone=UTC&characterEncoding=utf8",
                    System.getProperty("DB_HOST", "localhost"),
                    System.getProperty("DB_PORT", "3306"),
                    System.getProperty("DB_NAME", "openmanus"));
            case H2 -> "jdbc:h2:mem:openmanus;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE";
        };
    }

    /**
     * 获取数据库用户名
     */
    private String getDatabaseUsername(OpenManusProperties.PersistenceProperties.DatabaseType dbType) {
        return switch (dbType) {
            case POSTGRESQL, MYSQL -> System.getProperty("DB_USERNAME", "openmanus");
            case H2 -> "sa";
        };
    }

    /**
     * 获取数据库密码
     */
    private String getDatabasePassword(OpenManusProperties.PersistenceProperties.DatabaseType dbType) {
        return switch (dbType) {
            case POSTGRESQL, MYSQL -> System.getProperty("DB_PASSWORD", "openmanus123");
            case H2 -> "";
        };
    }
}
